package com.apes.fn.scm.purchaseReturn.service;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.mdm.purchase.PurchasingGroup;
import com.apes.fn.mdm.purchase.PurchasingGroupRepository;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfter;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfterItem;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfterJunior;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfterJuniorItem;
import com.apes.fn.scm.purchaseReturn.repository.PurchaseAfterJuniorRepository;
import com.apes.fn.scm.purchaseReturn.repository.PurchaseAfterRepository;
import com.apes.fn.tms.model.Site;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.Stock;
import com.apes.scm.account.account.repository.InventoryBatchRepository;
import com.apes.scm.account.account.repository.StockRepository;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.party.model.Corporate;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.service.PartyRoleService;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apestech.framework.xml.plugin.modul.Model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: apes-server
 * @BelongsPackage: com.apes.fn.scm.purchaseReturn.service
 * @ClassName: PurchaseAfterService
 * @Author: ljp
 * @CreateTime: 2021-01-19 14:49
 * @Description: 售后单服务
 * @Version: 1.0
 */
@Service("purchaseAfterService")
public class PurchaseAfterService extends DomainService {

    @Autowired
    private LocationRepository locationRepository;

    @Autowired
    private InventoryBatchRepository inventoryBatchRepository;

    @Autowired
    private StockRepository stockRepository;

    @Autowired
    private PurchaseAfterRepository purchaseAfterRepository;

    @Autowired
    private ProductAccountService productAccountService;

    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private PurchaseAfterJuniorRepository purchaseAfterJuniorRepository;
    @Autowired
    private SequenceService sequenceService;
    @Autowired
    private PartyRoleService partyRoleService;

    /**
     * 保存
     * @param request
     * @return
     */
    public PurchaseAfter create(SimpleRequest request) {
        PurchaseAfter purchaseAfter = request.getO(PurchaseAfter.class);
        purchaseAfter.setState("create");
        purchaseAfter = purchaseAfterRepository.saveAndFlush(purchaseAfter);
        updateQty(purchaseAfter,true,"售后单创建");
        return purchaseAfter;
    }

    /**
     * 编辑
     * @param request
     * @return
     */
    public PurchaseAfter update(SimpleRequest request) {
        PurchaseAfter newPurchaseAfter = request.getO(PurchaseAfter.class);
        PurchaseAfter oldPurchaseAfter = purchaseAfterRepository.findOne(newPurchaseAfter.getId());
        updateQty(oldPurchaseAfter,false,"售后单编辑");

        newPurchaseAfter.getPurchaseAfterItems().forEach( purchaseAfterItem -> {
            if (StringUtils.isEmpty(purchaseAfterItem.getId())) {
                purchaseAfterItem.setId(sequenceService.getId(PurchaseAfterItem.CONST_TABLE_NAME));
            }
        });
        newPurchaseAfter = purchaseAfterRepository.saveAndFlush(newPurchaseAfter);
        updateQty(newPurchaseAfter,true,"售后单编辑");
        return newPurchaseAfter;
    }

    /**
     * 删除
     * @param request
     * @return
     */
    public PurchaseAfter delete(SimpleRequest request) {
        PurchaseAfter purchaseAfter = request.getO(PurchaseAfter.class);
        purchaseAfter.setState("delete");
        purchaseAfter.setDeleteUid(request.getPerson());
        updateQty(purchaseAfter,false,"售后单删除");
        purchaseAfterRepository.saveAndFlush(purchaseAfter);
        return new PurchaseAfter();
    }

    /**
     * 提交
     * @param request
     * @return
     */
    public PurchaseAfter apply(SimpleRequest request) {
        PurchaseAfter purchaseAfter = request.getO(PurchaseAfter.class);
        purchaseAfter = purchaseAfterRepository.findOne(purchaseAfter.getId());
        purchaseAfter.setApplyUid(request.getPerson());
        purchaseAfter.setDateApply(new Date());
        purchaseAfter.setState("done");
        purchaseAfter = purchaseAfterRepository.saveAndFlush(purchaseAfter);
        createPurchaseAfterJunior(purchaseAfter);
        return purchaseAfter;
    }

    /**
     * 同一供应商拆单
     * @param purchaseAfter
     */
    public void createPurchaseAfterJunior(PurchaseAfter purchaseAfter) {
        Map<String, List<PurchaseAfterItem>> groupItems = purchaseAfter.getPurchaseAfterItems().stream().collect(Collectors.groupingBy(e -> e.getSupplier().getId()));

        for (Map.Entry<String, List<PurchaseAfterItem>> map : groupItems.entrySet()) {
            List<PurchaseAfterItem> items =  map.getValue();

            PurchaseAfterJunior purchaseAfterJunior = new PurchaseAfterJunior();
            purchaseAfterJunior.setSource(purchaseAfter.getId());
            purchaseAfterJunior.setLocation(purchaseAfter.getLocation());
            purchaseAfterJunior.setCompany(purchaseAfter.getCompany());
            purchaseAfterJunior.setState("apply");
            purchaseAfterJunior.setNote(purchaseAfter.getNote());
            purchaseAfterJunior.setSite(purchaseAfter.getSite());
            purchaseAfterJunior.setCreateUid(purchaseAfter.getApplyUid());
            purchaseAfterJunior.setCreateDate(purchaseAfter.getDateApply());
            purchaseAfterJunior.setApplyUid(purchaseAfter.getApplyUid());
            purchaseAfterJunior.setApplyDate(new Date());
            purchaseAfterJunior.setReturnReason(purchaseAfter.getReturnReason());

            Set<PurchaseAfterJuniorItem> purchaseAfterJuniorItems = new HashSet<>();
            items.forEach(item-> {
                PurchaseAfterJuniorItem purchaseAfterJuniorItem = new PurchaseAfterJuniorItem();
                purchaseAfterJuniorItem.setProduct(item.getProduct());
                purchaseAfterJuniorItem.setUom(item.getUom());
                purchaseAfterJuniorItem.setPriceUnit(item.getPriceUnit());
                purchaseAfterJuniorItem.setSupplier(item.getSupplier());
                purchaseAfterJuniorItem.setInventoryBatch(item.getInventoryBatch());
                purchaseAfterJuniorItem.setNote(item.getNote());
                purchaseAfterJuniorItem.setImgs(item.getImgs());
                purchaseAfterJuniorItem.setProductQty(item.getProductQty());
                purchaseAfterJuniorItem.setReturnQty(item.getProductQty());
                purchaseAfterJuniorItem.setPurchaseInDate(item.getPurchaseInDate());
                purchaseAfterJuniorItem.setOriginalInventoryBatch(item.getOriginalInventoryBatch());
                purchaseAfterJuniorItem.setOriginalSupplier(item.getOriginalSupplier());
                purchaseAfterJuniorItem.setOriginalPriceUnit(item.getOriginalPriceUnit());
                purchaseAfterJuniorItem.setCooperation(item.getCooperation());
                purchaseAfterJuniorItems.add(purchaseAfterJuniorItem);
            });

            purchaseAfterJunior.setPurchaseAfterJuniorItems(purchaseAfterJuniorItems);
            purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
        }

    }


    public void updateQty(PurchaseAfter purchaseAfter, boolean flag, String note) {
        purchaseAfter.getPurchaseAfterItems().forEach(item->{
            double productAccountQty = flag?-1*item.getProductQty():item.getProductQty();
            double inventoryQty = flag?item.getProductQty():-1*item.getProductQty();
            // 减少（增加）商品可用数
            productAccountService.setProductAvailable(item.getProduct(), purchaseAfter.getLocation(),
                    item.getUom(), productAccountQty, purchaseAfter.getInnerBusinessType(), purchaseAfter.getId(),
                    item.getId(), note, purchaseAfter.getCompany());
            //减少（增加）商品批次冻结数
            inventoryService.changeFrostQty(item.getInventoryBatch(), item.getUom(), inventoryQty, purchaseAfter.getCompany(),
                    purchaseAfter.getInnerBusinessType(), purchaseAfter.getId(),
                    item.getId(), note);
        });
    }



    public Page findAllInventoryBatch(SimpleRequest request) {
        if (request.getJO().toString().contains("key")) return null;

        Location location = parseLocation(request);
        //批次
        List<Map> condition = jointInventoryBatchData(request, location);
         List<InventoryBatch> inventoryBatches = inventoryBatchRepository.findAll(JpaDsl.toCriteria(condition))
                .stream().filter(e -> e.getBalanceQty() > e.getFrostQty()).collect(Collectors.toList());

//        inventoryBatches = inventoryBatches.stream().filter(inventoryBatch -> !inventoryBatch.getSupplier().getParty().getPartyRoles().stream().anyMatch(e->e.getRole().getId().equals("Company")))
//                .collect(Collectors.toList());
        //库存账
        List<Map> stockcondition = jointStockData(request, location);
        List<Stock> stocks = stockRepository.findAll(JpaDsl.toCriteria(stockcondition))
                .stream().filter(e -> e.getUsableQty() > e.getFrozenQty()).collect(Collectors.toList());

        List<Map> result = setData(inventoryBatches, stocks,location.getCompany());
        return autoPage(request,result);
    }

    public List<Map> setData(List<InventoryBatch> inventoryBatches, List<Stock> stocks, PartyRole companyId) {
        List<Map> result = new ArrayList<>();
        inventoryBatches.forEach(inventoryBatch -> {
            List<Stock> stockList = stocks.stream().filter(stock -> stock.getProduct().getId().equals(inventoryBatch.getProduct().getId())).collect(Collectors.toList());
            if (stockList.size() == 0) return;
            double stockQty = stockList.get(0).getUsableQty() - stockList.get(0).getFrozenQty();
            double inventorybatchQty = inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty();
            double canReturnQty = stockQty > inventorybatchQty ? inventorybatchQty : stockQty;
            if (canReturnQty < 0) canReturnQty = 0;

            Map map = new HashMap();
            map.put("id", inventoryBatch.getId());
            map.put("product", inventoryBatch.getProduct());
            map.put("uom", inventoryBatch.getUom());
            map.put("supplier", inventoryBatch.getSupplier());//供应商
            map.put("canReturnQty", canReturnQty);//可退数量
            map.put("stockQty", stockQty);//库存可用数量
            map.put("inventorybatchQty", inventorybatchQty);//批次可用数量
            map.put("priceUnit", inventoryBatch.getTaxCostPrice());//含税单价
            map.put("purchaseInDate", inventoryBatch.getPurchaseInDate().toString());//入库时间
            map.put("cooperation", inventoryBatch.getCooperation());//合作方式
            map.put("originalSupplier", changeSupplier(inventoryBatch.getSupplier()));//原供应商
            map.put("originalInventoryBatch", inventoryBatch.getId());//原批次内码
            map.put("originalPriceUnit", inventoryBatch.getTaxCostPrice());//原单价

            boolean isInner = inventoryBatch.getSupplier().getParty().getCorporate().inner();
            if (isInner) {
                PartyRole company = getCompany(inventoryBatch.getSupplier());
                PartyRole supplier = getCustomer(companyId);
                List<Map> rows = purchaseAfterRepository.findOriginalInventorybach(company.getId(), supplier.getId(), inventoryBatch.getProduct().getId());
                if (!rows.isEmpty()) {
                    long upInventoryId = Long.valueOf(rows.get(0).get("INVENTORY_ID").toString());
                    InventoryBatch batch = inventoryBatchRepository.findOne(upInventoryId);
                    map.put("originalSupplier", batch.getSupplier());//原供应商
                    map.put("originalInventoryBatch", batch.getId());//原批次内码
                    map.put("originalPriceUnit", batch.getTaxCostPrice());//原单价
                    result.add(map);
                }
            }
            if (!isInner) {
                result.add(map);
            }
        });
        return result;
    }

    /**
     *更改真实供应商
     */
    public PartyRole changeSupplier(PartyRole supplier){
        if (supplier.getName().contains("[")) return supplier;
        if(supplier.getId().contains("A") || supplier.getId().contains("G") || supplier.getId().contains("004465")) {
            supplier.setName("[" + supplier.getId() + "]" + supplier.getName());
        } else {
                supplier.setName("[G1007]广州市车宝网络科技有限公司");
            }
        return supplier;
    }

    public Page autoPage(SimpleRequest request,List<Map> result) {
        List<Map> pageResult;
        int page = Integer.valueOf(request.get("page").toString());
        int size = Integer.valueOf(request.get("size").toString());
        if (result.size() < page*size) return null;
        if (result.size() <= size*(page +1)) {
            pageResult  = result.subList(page*size,result.size());
        }else {
            pageResult  = result.subList(page*size,size*(page +1));
        }
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        PageImpl pageImpl = new PageImpl<>(pageResult, pageable, result.size());
        return pageImpl;
    }

    /**
     *查找仓库
     */
    public Location parseLocation(SimpleRequest request) {
        JSONObject domain = request.get("domain");
        JSONArray filters = domain.getJSONArray("filters");
        String location = filters.getJSONObject(0).get("value").toString();
        return locationRepository.findOne(location);
    }

    public List<Map> jointInventoryBatchData(SimpleRequest request,Location location) {
        List<Map> condition = request.get("condition");
        condition.add(mapper("field","company","value",location.getCompany(),"operator","EQ"));
        condition.add(mapper("field","balanceQty","value",0,"operator","GT"));
        return condition;
    }

    public List<Map> jointStockData(SimpleRequest request,Location location) {
        List<Map> stockCondition = request.get("condition");
        stockCondition = stockCondition.stream().filter(e->!e.get("field").equals("id")).collect(Collectors.toList());
        stockCondition.add(mapper("field","location","value",location,"operator","EQ"));
        stockCondition.add(mapper("field","usableQty","value",0,"operator","GT"));
        return stockCondition;
    }

    /**
     * 找到站点
     */
    public Site findSite(SimpleRequest request) {
        String locationId = request.get("id").toString();
        Location location = locationRepository.findOne(locationId);
        List<PurchasingGroup> groupList = SpringManager.getBean(PurchasingGroupRepository.class)
                .findAll(JpaDsl.toCriteriaByEq("depts.id", location.getDept().getId()));
        if (groupList.size()==0) return null;
        return groupList.get(0).getSite();
    }

    /**
     *查询运营模式
     */
    public Enumeration findCorporate(SimpleRequest request){
        String id = request.get("id");
        PartyRole company = partyRoleService.findOne(id,"Company");
        Enumeration operation = company.getParty().getCorporate().getOperation();
        return operation;
    }

    /**
     * 公司
     */
    protected PartyRole getCompany(PartyRole owner) {
        PartyRole customer = partyRoleService.findByPartyAndRole(owner.getParty().getId(), "Company");
        if (customer == null) throw new RuntimeException("内部公司：" + owner.getName() + " 没有定义公司角色！");
        return customer;
    }

    /**
     * 客户
     */
    protected PartyRole getCustomer(PartyRole owner) {
        PartyRole customer = partyRoleService.findByPartyAndRole(owner.getParty().getId(), "Customer");
        if (customer == null) throw new RuntimeException("内部公司：" + owner.getName() + " 没有定义客户角色，不允许跨公司交易！");
        return customer;
    }

}
